<!DOCTYPE html>

<html>
<head>
  <title>calculate.coffee</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page">
            
              
              <a class="source" href="analyze.html">
                analyze.coffee
              </a>
            
              
              <a class="source" href="autoload.html">
                autoload.coffee
              </a>
            
              
              <a class="source" href="blender.html">
                blender.coffee
              </a>
            
              
              <a class="source" href="calculate.html">
                calculate.coffee
              </a>
            
              
              <a class="source" href="caman.html">
                caman.coffee
              </a>
            
              
              <a class="source" href="convert.html">
                convert.coffee
              </a>
            
              
              <a class="source" href="event.html">
                event.coffee
              </a>
            
              
              <a class="source" href="filter.html">
                filter.coffee
              </a>
            
              
              <a class="source" href="io.html">
                io.coffee
              </a>
            
              
              <a class="source" href="layer.html">
                layer.coffee
              </a>
            
              
              <a class="source" href="logger.html">
                logger.coffee
              </a>
            
              
              <a class="source" href="module.html">
                module.coffee
              </a>
            
              
              <a class="source" href="pixel.html">
                pixel.coffee
              </a>
            
              
              <a class="source" href="plugin.html">
                plugin.coffee
              </a>
            
              
              <a class="source" href="renderer.html">
                renderer.coffee
              </a>
            
              
              <a class="source" href="store.html">
                store.coffee
              </a>
            
              
              <a class="source" href="util.html">
                util.coffee
              </a>
            
              
              <a class="source" href="blenders.html">
                blenders.coffee
              </a>
            
              
              <a class="source" href="filters.html">
                filters.coffee
              </a>
            
              
              <a class="source" href="size.html">
                size.coffee
              </a>
            
              
              <a class="source" href="blur.html">
                blur.coffee
              </a>
            
              
              <a class="source" href="camera.html">
                camera.coffee
              </a>
            
              
              <a class="source" href="compoundBlur.html">
                compoundBlur.coffee
              </a>
            
              
              <a class="source" href="edges.html">
                edges.coffee
              </a>
            
              
              <a class="source" href="posterize.html">
                posterize.coffee
              </a>
            
              
              <a class="source" href="presets.html">
                presets.coffee
              </a>
            
              
              <a class="source" href="rotate.html">
                rotate.coffee
              </a>
            
              
              <a class="source" href="stackBlur.html">
                stackBlur.coffee
              </a>
            
              
              <a class="source" href="threshold.html">
                threshold.coffee
              </a>
            
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>calculate.coffee</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              <p>Various math-heavy helpers that are used throughout CamanJS.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">Caman</span>.<span class="title">Calculate</span></span></pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>Calculates the distance between two points.</p>
<p>@param [Number] x1 1st point x-coordinate.
@param [Number] y1 1st point y-coordinate.
@param [Number] x2 2nd point x-coordinate.
@param [Number] y2 2nd point y-coordinate.
@return [Number] The distance between the two points.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@distance</span>: (x1, y1, x2, y2) -&gt;
    Math.sqrt Math.pow(x2 - x1, <span class="number">2</span>) + Math.pow(y2 - y1, <span class="number">2</span>)</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>Generates a pseudorandom number that lies within the max - mix range. The number can be either 
an integer or a float depending on what the user specifies.</p>
<p>@param [Number] min The lower bound (inclusive).
@param [Number] max The upper bound (inclusive).
@param [Boolean] getFloat Return a Float or a rounded Integer?
@return [Number] The pseudorandom number, either as a float or integer.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@randomRange</span>: (min, max, getFloat = <span class="literal">false</span>) -&gt;
    rand = min + (Math.random() * (max - min))
    <span class="keyword">return</span> <span class="keyword">if</span> getFloat <span class="keyword">then</span> rand.toFixed(getFloat) <span class="keyword">else</span> Math.round(rand)</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>Calculates the luminance of a single pixel using a special weighted sum.
@param [Object] rgba RGBA object describing a single pixel.
@return [Number] The luminance value of the pixel.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@luminance</span>: (rgba) -&gt; (<span class="number">0.299</span> * rgba.r) + (<span class="number">0.587</span> * rgba.g) + (<span class="number">0.114</span> * rgba.b)</pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>Generates a bezier curve given a start and end point, with control points in between.
Can also optionally bound the y values between a low and high bound.</p>
<p>This is different than most bezier curve functions because it attempts to construct it in such 
a way that we can use it more like a simple input -&gt; output system, or a one-to-one function. 
In other words we can provide an input color value, and immediately receive an output modified 
color value.</p>
<p>Note that, by design, this does not force X values to be in the range [0..255]. This is to
generalize the function a bit more. If you give it a starting X value that isn&#39;t 0, and/or a
ending X value that isn&#39;t 255, you may run into problems with your filter!</p>
<p>@param [Array] 2-item arrays describing the x, y coordinates of the control points. Minimum two.
@param [Number] lowBound (optional) Minimum possible value for any y-value in the curve.
@param [Number] highBound (optional) Maximum posisble value for any y-value in the curve.
@return [Array] Array whose index represents every x-value between start and end, and value
  represents the corresponding y-value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@bezier</span>: (start, ctrl1, ctrl2, end, lowBound = <span class="number">0</span>, highBound = <span class="number">255</span>) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>(controlPoints, lowBound, highBound) -&gt;
4.0 shim - change declaration to (controlPoints, lowBound, highBound) at 5.0</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="keyword">if</span> start[<span class="number">0</span>] <span class="keyword">instanceof</span> Array
      controlPoints = start
      lowBound = ctrl1
      highBound = ctrl2
    <span class="keyword">else</span>
      controlPoints = [start, ctrl1, ctrl2, end]

    <span class="keyword">if</span> controlPoints.length &lt; <span class="number">2</span>
      <span class="keyword">throw</span> <span class="string">"Invalid number of arguments to bezier"</span>

    bezier = {}
    <span class="function"><span class="title">lerp</span></span> = (a, b, t) -&gt; <span class="keyword">return</span> a * (<span class="number">1</span> - t) + b * t
    <span class="function"><span class="title">clamp</span></span> = (a, min, max) -&gt; <span class="keyword">return</span> Math.min(Math.max(a, min), max)

    <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>.<span class="number">.1000</span>]
      t = i / <span class="number">1000</span>
      prev = controlPoints

      <span class="keyword">while</span> prev.length &gt; <span class="number">1</span>
        next = []

        <span class="keyword">for</span> j <span class="keyword">in</span> [<span class="number">0.</span>.(prev.length - <span class="number">2</span>)]
          next.push([
            lerp(prev[j][<span class="number">0</span>], prev[j + <span class="number">1</span>][<span class="number">0</span>], t),
            lerp(prev[j][<span class="number">1</span>], prev[j + <span class="number">1</span>][<span class="number">1</span>], t)
          ])

        prev = next

      bezier[Math.round(prev[<span class="number">0</span>][<span class="number">0</span>])] = Math.round(clamp(prev[<span class="number">0</span>][<span class="number">1</span>], lowBound, highBound))

    endX = controlPoints[controlPoints.length - <span class="number">1</span>][<span class="number">0</span>]
    bezier = Caman.Calculate.missingValues(bezier, endX)</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>Edge case</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    bezier[endX] = bezier[endX - <span class="number">1</span>] <span class="keyword">if</span> <span class="keyword">not</span> bezier[endX]?

    <span class="keyword">return</span> bezier</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>Generates a hermite curve given a start and end point, with control points in between.
Can also optionally bound the y values between a low and high bound.</p>
<p>This is different than most hermite curve functions because it attempts to construct it in such 
a way that we can use it more like a simple input -&gt; output system, or a one-to-one function. 
In other words we can provide an input color value, and immediately receive an output modified 
color value.</p>
<p>Note that, by design, this does not force X values to be in the range [0..255]. This is to
generalize the function a bit more. If you give it a starting X value that isn&#39;t 0, and/or a
ending X value that isn&#39;t 255, you may run into problems with your filter!</p>
<p>@param [Array] 2-item arrays describing the x, y coordinates of the control points. Minimum two.
@param [Number] lowBound (optional) Minimum possible value for any y-value in the curve.
@param [Number] highBound (optional) Maximum possible value for any y-value in the curve.
@return [Array] Array whose index represents every x-value between start and end, and value
  represents the corresponding y-value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@hermite</span>: (controlPoints, lowBound, highBound) -&gt;
    <span class="keyword">if</span> controlPoints.length &lt; <span class="number">2</span>
        <span class="keyword">throw</span> <span class="string">"Invalid number of arguments to hermite"</span>

    ret = {}

    <span class="function"><span class="title">lerp</span></span> = (a, b, t) -&gt; <span class="keyword">return</span> a * (<span class="number">1</span> - t) + b * t
    <span class="function"><span class="title">add</span></span> = (a, b, c, d) =&gt; [a[<span class="number">0</span>] + b[<span class="number">0</span>] + c[<span class="number">0</span>] + d[<span class="number">0</span>], a[<span class="number">1</span>] + b[<span class="number">1</span>] + c[<span class="number">1</span>] + d[<span class="number">1</span>]]
    <span class="function"><span class="title">mul</span></span> = (a, b) =&gt; [a[<span class="number">0</span>] * b[<span class="number">0</span>], a[<span class="number">1</span>] * b[<span class="number">1</span>]]
    <span class="function"><span class="title">sub</span></span> = (a, b) =&gt; [a[<span class="number">0</span>] - b[<span class="number">0</span>], a[<span class="number">1</span>] - b[<span class="number">1</span>]]
    <span class="function"><span class="title">clamp</span></span> = (a, min, max) -&gt; <span class="keyword">return</span> Math.min(Math.max(a, min), max)

    count = <span class="number">0</span>
    <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>.controlPoints.length - <span class="number">2</span>]
      p0 = controlPoints[i]
      p1 = controlPoints[i + <span class="number">1</span>]

      pointsPerSegment = p1[<span class="number">0</span>] - p0[<span class="number">0</span>]
      pointsPerStep = <span class="number">1</span> / pointsPerSegment</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>the last point of the last segment should reach p1</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      <span class="keyword">if</span>(i == controlPoints.length - <span class="number">2</span>)
        pointsPerStep = <span class="number">1</span> / (pointsPerSegment - <span class="number">1</span>)

      p = <span class="keyword">if</span> i &gt; <span class="number">0</span> <span class="keyword">then</span> controlPoints[i - <span class="number">1</span>] <span class="keyword">else</span> p0
      m0 = mul(sub(p1, p), [<span class="number">0.5</span>, <span class="number">0.5</span>])

      p = <span class="keyword">if</span> i &lt; controlPoints.length - <span class="number">2</span> <span class="keyword">then</span> controlPoints[i + <span class="number">2</span>] <span class="keyword">else</span> p1
      m1 = mul(sub(p, p0), [<span class="number">0.5</span>, <span class="number">0.5</span>])

      <span class="keyword">for</span> j <span class="keyword">in</span> [<span class="number">0.</span>.pointsPerSegment]
        t = j * pointsPerStep

        fac0 = <span class="number">2.0</span> * t * t * t - <span class="number">3.0</span> * t * t + <span class="number">1.0</span>
        fac1 = t * t * t - <span class="number">2.0</span> * t * t + t
        fac2 = -<span class="number">2.0</span> * t * t * t + <span class="number">3.0</span> * t * t
        fac3 = t * t * t - t * t

        pos = add(mul(p0, [fac0, fac0]), mul(m0, [fac1, fac1]), mul(p1, [fac2, fac2]), mul(m1, [fac3, fac3]))

        ret[Math.round(pos[<span class="number">0</span>])] = Math.round(clamp(pos[<span class="number">1</span>], lowBound, highBound))

        count += <span class="number">1</span></pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>add missing values</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    endX = controlPoints[controlPoints.length - <span class="number">1</span>][<span class="number">0</span>]
    ret = Caman.Calculate.missingValues(ret, endX)

    <span class="keyword">return</span> ret</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>Calculates possible missing values from a given value array. Note that this returns a copy
and does not mutate the original. In case no values are missing the original array is
returned as that is convenient.</p>
<p>@param [Array] 2-item arrays describing the x, y coordinates of the control points.
@param [Number] end x value of the array (maximum)
@return [Array] Array whose index represents every x-value between start and end, and value
  represents the corresponding y-value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="property">@missingValues</span>: (values, endX) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <p>Do a search for missing values in the bezier array and use linear
interpolation to approximate their values</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="keyword">if</span> Object.keys(values).length &lt; endX + <span class="number">1</span>
      ret = {}

      <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>.endX]
        <span class="keyword">if</span> values[i]?
          ret[i] = values[i]
        <span class="keyword">else</span>
          leftCoord = [i - <span class="number">1</span>, ret[i - <span class="number">1</span>]]</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>Find the first value to the right. Ideally this loop will break
very quickly.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>          <span class="keyword">for</span> j <span class="keyword">in</span> [i..endX]
            <span class="keyword">if</span> values[j]?
              rightCoord = [j, values[j]]
              <span class="keyword">break</span>

          ret[i] = leftCoord[<span class="number">1</span>] +
            ((rightCoord[<span class="number">1</span>] - leftCoord[<span class="number">1</span>]) / (rightCoord[<span class="number">0</span>] - leftCoord[<span class="number">0</span>])) *
            (i - leftCoord[<span class="number">0</span>])

      <span class="keyword">return</span> ret

    <span class="keyword">return</span> values

Calculate = Caman.Calculate</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
